package impl;

import interfaces.MapRobots;
import interfaces.RobotInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import candySystemNamespace.CandyWorld;
import candySystemNamespace.Map;
import candySystemNamespace.TransComponent;
import classes.Constants;
import classes.Coordinate;
import classes.ObservableList;
import classes.Utils;

public class CandyWorldImpl extends CandyWorld {
	private final String TAG = Constants.TAG + "." + getClass().getSimpleName();

	/** List of species that connect the robots to the map */
	private List<TransSpecie.Component> transmitters = new ArrayList<TransSpecie.Component>();

	private Map map;

	private int candiesNumber = 0;
	private int robotsNumber = 0;
	private int mapWidth = 0;
	private int mapHeight = 0;
	
	public CandyWorldImpl(int candiesNumber, int robotsNumber, int mapWidth, int mapHeight) {
		Utils.logC(TAG, "CandyWorld created: " + candiesNumber + " | " + robotsNumber);
		this.candiesNumber = candiesNumber;
		this.robotsNumber = robotsNumber;
		this.mapHeight = mapHeight;
		this.mapWidth = mapWidth;
	}

	@Override
	protected void start() {
		super.start();
		
		init();
	}

	private void init() {
		if (map == null)
			map = new MapImpl(mapWidth, mapHeight, candiesNumber);
		
		// TODO Listen in order to detect if a place with robots has become obstacle
		// parts().map().mapPositions().getFreePositions().addListener(this);
		
		// Create and place robots
		int robotsHeight = mapHeight / 2;
		int robotsWidth = robotsNumber / robotsHeight + (robotsNumber % robotsHeight != 0 ? 1 : 0);
		int count = 0;
		for (int i = mapWidth - 1; i > mapWidth - robotsWidth - 1; i--)
			for (int j = mapHeight / 4; j < robotsHeight + mapHeight / 4; j++) {
				if (count >= robotsNumber)
					break;
				
				transmitters.add(newTransSpecie(i, j));
				parts().map().mapPositions().getFreePositions().remove(new Coordinate(i, j));
				count++;
			}
	}

	@Override
	protected Map make_map() {
		if (map == null)
			map = new MapImpl(mapWidth, mapHeight, candiesNumber);
		
		return map;
	}

	@Override
	protected TransComponent make_trans() {
		return new TransComponentImpl();
	}

	@Override
	protected TransSpecie make_TransSpecie(int x, int y) {
		return new TransSpecieImpl(x, y);
	}

	@Override
	protected MapRobots make_robotsInfo() {
		return new MapRobots() {

			@Override
			public ObservableList<RobotInfo> getRobotsInfo() {
				ObservableList<RobotInfo> temp = new ObservableList<RobotInfo>();

				ListIterator<TransSpecie.Component> itr = transmitters.listIterator();
				while (itr.hasNext()) {
					final TransSpecie.Component trans = itr.next();
					if (trans.info().getState() == RobotImpl.STATE_DEAD) {
						// Remove dead robot from list
						itr.remove();
					} else if (trans.info().getState() == RobotImpl.STATE_KILLED_SELF) {
						// Recreate a robot in the new modified position
						int x = trans.info().getPosition().getX();
						int y = trans.info().getPosition().getY();
						itr.remove();
						transmitters.add(newTransSpecie(x, y));
					} else {
						temp.add(new RobotInfo() {
							@Override
							public boolean hasCandy() {
								return trans.info().hasCandy();
							}
							@Override
							public int getState() {
								return trans.info().getState();
							}
							@Override
							public Coordinate getPosition() {
								return trans.info().getPosition();
							}
						});
					}
				}

				return temp;
			}
		};
	}
}
